package com.jdone.compus.controller;

import com.jdone.compus.dto.*;
import com.jdone.compus.model.BlowUsageRecord;
import com.jdone.compus.service.BlowUsageRecordService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Row;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.time.LocalDate;
import java.util.Map;

@RestController
@RequestMapping("/blow/usage-records")
@Api(value = "吹风使用记录管理", tags = "吹风使用记录管理")
public class BlowUsageRecordController {

    @Autowired
    private BlowUsageRecordService service;

    @ApiOperation("新增使用记录")
    @PostMapping("/wechat/add")
    public ApiResponse add(@RequestBody BlowUsageRecord dto) {
        try {
            BlowUsageRecord record = service.create(dto);
            return ApiResponse.success(record);
        } catch (Exception e) {
            return ApiResponse.error(e.getMessage());
        }
    }

    @ApiOperation("根据ID查询使用记录")
    @GetMapping("/end_back/find/{id}")
    public ApiResponse getById(@PathVariable Long id) {
        try {
            return ApiResponse.success(service.getById(id));
        } catch (RuntimeException ex) {
            return ApiResponse.error(ex.getMessage());
        }
    }

    @ApiOperation("WeChat分页查询使用记录（可传 DTO 做多条件过滤）")
    @GetMapping("/wechat/findAll")
    public ApiResponse list(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size,
            @ModelAttribute BlowUsageRecordQuery query
    ) {
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by("borrowTime").descending());
        Page<com.jdone.compus.dto.BlowUsageRecordDto> result = service.findByCriteria(query, pageable);
        return ApiResponse.success(result);
    }


    @ApiOperation("分页查询使用记录（可传 DTO 做多条件过滤）")
    @GetMapping("/findAll")
    public ApiResponse listFindAll(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size,
            @ModelAttribute BlowUsageRecordQuery query
    ) {
//        System.out.println("query:  " + query.toString());
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by("borrowTime").descending());
        Page<com.jdone.compus.dto.BlowUsageRecordDto> result = service.findByCriteria(query, pageable);
//        System.out.println(result);
        return ApiResponse.success(result);
    }

    @ApiOperation("修改使用记录")
    @PutMapping("/end_back/update/{id}")
    public ApiResponse update(@PathVariable Long id, @RequestBody BlowUsageRecord dto) {
        try {
            return ApiResponse.success(service.update(id, dto));
        } catch (RuntimeException ex) {
            return ApiResponse.error(ex.getMessage());
        }
    }

    @ApiOperation("删除使用记录")
    @DeleteMapping("/end_back/delete/{id}")
    public ApiResponse delete(@PathVariable Long id) {
        try {
            service.delete(id);
            return ApiResponse.success("删除成功");
        } catch (RuntimeException ex) {
            return ApiResponse.error(ex.getMessage());
        }
    }

    @ApiOperation("统计接口--统计已支付订单总数与总金额（按开始/结束日期，可选）")
    @GetMapping("/stats")
    public ApiResponse stats(
            @RequestParam(value = "start", required = false)
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate start,

            @RequestParam(value = "end", required = false)
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end
    ) {
        Map<String, Object> stats = service.getPaidOrderStats(start, end);
        return ApiResponse.success(stats);
    }

    @ApiOperation("统计接口—按天统计已支付订单消费总金额（开始/结束日期可选）")
    @GetMapping("/daily-fee")
    public ApiResponse dailyFee(
            @RequestParam(value = "start", required = false)
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate start,

            @RequestParam(value = "end", required = false)
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end
    ) {
        List<DailyFeeDTO> list = service.getDailyFee(start, end);
        return ApiResponse.success(list);
    }


    @ApiOperation("导出使用记录（Excel 全量，流式 SXSSFWorkbook）")
    @GetMapping("/export")
    public void export(
            @ModelAttribute BlowUsageRecordQuery query,
            HttpServletResponse response
    ) throws IOException {
        // 0. 防止 Spring MVC 已经写入过其它内容导致文件损坏
        response.reset();

        // 1. 查询全量数据
        List<BlowUsageRecord> list = service.findByCriteria(query);

        // 2. 设置响应头（UTF-8 + URLEncoder 保证中文文件名不乱码）
        String filename = "吹风使用记录_" +
                LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) +
                ".xlsx";
        String encodedName = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition",
                "attachment; filename*=UTF-8''" + encodedName);

        // 3. 流式写 Workbook，保留 100 行到内存
        try (
                SXSSFWorkbook wb = new SXSSFWorkbook(100);
                ServletOutputStream out = response.getOutputStream()
        ) {
            Sheet sheet = wb.createSheet("使用记录");
            // 简单示例：设置前两列宽度，可按需调整
            sheet.setColumnWidth(0, 10 * 256);
            sheet.setColumnWidth(1, 20 * 256);

            // 4. 写表头
            Row header = sheet.createRow(0);
            String[] titles = {
                    "ID", "业务订单号", "IMEI", "生产厂家",
                    "使用人", "账号", "电话", "借用时间",
                    "归还时间", "分钟数", "金额", "状态",
                    "创建时间", "更新时间"
            };
            for (int i = 0; i < titles.length; i++) {
                header.createCell(i).setCellValue(titles[i]);
            }

            // 5. 写数据行
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            for (int i = 0; i < list.size(); i++) {
                BlowUsageRecord r = list.get(i);
                Row row = sheet.createRow(i + 1);
                int c = 0;
                row.createCell(c++).setCellValue(r.getId());
                row.createCell(c++).setCellValue(r.getBusinessOrderNo());
                row.createCell(c++).setCellValue(r.getImei());
                row.createCell(c++).setCellValue(r.getManufacturer());
                row.createCell(c++).setCellValue(r.getUsername());
                row.createCell(c++).setCellValue(r.getUserAccount());
                row.createCell(c++).setCellValue(r.getUserPhone());
                row.createCell(c++).setCellValue(r.getBorrowTime().format(dtf));
                row.createCell(c++)
                        .setCellValue(r.getReturnTime() != null ? r.getReturnTime().format(dtf) : "");
                row.createCell(c++).setCellValue(r.getMinutes());
                row.createCell(c++)
                        .setCellValue(r.getFee() != null ? r.getFee().toString() : "");
//                row.createCell(c++).setCellValue(r.getOrderStatus().name());
                row.createCell(c++).setCellValue(r.getOrderStatus().getChineseName());
                row.createCell(c++).setCellValue(r.getCreatedAt().format(dtf));
                row.createCell(c++).setCellValue(r.getUpdatedAt().format(dtf));
            }

            // 6. 写出并释放临时文件
            wb.write(out);
            out.flush();
            wb.dispose();
        }
    }

    @ApiOperation("8/10统计接口--获取按天或按月的消费统计。参数 granularity=day|month")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startDate", value = "开始日期（可选）。按 day: 格式 yyyy-MM-dd；按 month: 格式 yyyy-MM。若不传则从数据库最早记录开始", required = false, dataType = "string", paramType = "query", example = "2025-07-01"),
            @ApiImplicitParam(name = "endDate", value = "结束日期（可选）。按 day: 格式 yyyy-MM-dd；按 month: 格式 yyyy-MM。若不传则到数据库最新记录结束", required = false, dataType = "string", paramType = "query", example = "2025-07-31"),
            @ApiImplicitParam(name = "granularity", value = "统计粒度，必填：'day' 或 'month'。示例：day=按天统计，month=按月统计", required = true, dataType = "string", paramType = "query", example = "day")
    })
    @GetMapping("/statsByDayOrMonth")
    public ApiResponse getStats(
            @RequestParam(value = "startDate", required = false) String startDate,    // yyyy-MM-dd 或 yyyy-MM（可选）
            @RequestParam(value = "endDate", required = false) String endDate,        // 可选
            @RequestParam(value = "granularity") String granularity               // 必填：day 或 month

    ) {
        try {
            List<DayStatusStatsDTO> data = service.getUsageStats(startDate, endDate, granularity);
            return new ApiResponse(0, true, "OK", data);
        } catch (IllegalArgumentException ex) {
            return new ApiResponse(400, false, ex.getMessage(), null);
        } catch (Exception ex) {
            return new ApiResponse(500, false, "服务异常", null);
        }
    }
}


